package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.aliyun.GreenImageScan;
import com.heima.aliyun.GreenTextScan;
import com.heima.common.constants.message.PublishArticleConstants;
import com.heima.common.constants.wemedia.WemediaConstants;
import com.heima.common.exception.CustException;
import com.heima.feigns.AdminFeign;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Autowired
    WmNewsMapper wmNewsMapper;
    @Value("${file.oss.web-site}")
    String webSite;
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Override
    public void autoScanWmNews(Integer newId) {
    //1.检查参数
        if (newId==null){
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
    //2.根据文章id查询文章
        //文章是否为空
        WmNews wmNews = wmNewsMapper.selectById(newId);
        if (wmNews==null){
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
    //检查文章状态是否为待审核
        if (!WemediaConstants.WM_NEWS_SUMMIT_STATUS.equals(wmNews.getStatus())){
            CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW,"文章不是待审核状态，无法进行审核");
        }
    //3.审核文章
    //3.1 抽取文章中 所有的文本内容 和图片内容
    //抽取出文章中 所有的文本内容 和 所有的图片url集合    Map<String,Object>  key: content 文本内容  value:string 文本内容
    // key：images 图片集合，List<String>    图片url集合
        Map<String,Object>  contentAndImages= handleTextAndImages(wmNews);
    //3.2 DFA敏感词审核
        boolean isSensitive = handleSensitive((String)contentAndImages.get("content"),wmNews);
        if(!isSensitive) return;
    //3.3 阿里云文本内容审核
        boolean isTestScan = handleText((String) contentAndImages.get("content"),wmNews);
        if (!isTestScan) return;
    //3.4阿里云图片审核
//        boolean isImageScan = handleImage((List<String>) contentAndImages.get("images"),wmNews);
        boolean isImageScan = handleImage((List<String>) contentAndImages.get("images"), wmNews);
        if (!isImageScan) return;
    //4.将文章状态修改为8 审核通过
        updateWmNews(wmNews,WmNews.Status.SUCCESS.getCode(),"审核通过");
    //5.根据文章的发布时间 延时发布文章
        long publishTime = wmNews.getPublishTime().getTime();//发布时间
        long nowTime = System.currentTimeMillis();//当前时间
        long remainTime=(publishTime-nowTime);//距离发布的时间
        rabbitTemplate.convertAndSend(PublishArticleConstants.DELAY_DIRECT_EXCHANGE,
                PublishArticleConstants.PUBLISH_ARTICLE_ROUTE_KEY,
                wmNews.getId()
                , new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        //对消息做后置处理 设置消息 x-delay 延时时间
                        message.getMessageProperties().setHeader("x-delay",remainTime<=0 ? 0:remainTime);
                        return message;
                    }
                });

    }

    @Autowired
    GreenImageScan greenImageScan;

    /**
     * 阿里云 审核图片安全
     * block status=2 review status=3
     * @param images
     * @param wmNews
     * @return
     */
    private boolean handleImage(List<String> images, WmNews wmNews) {
        boolean flag=true;
        try {

            Map map = greenImageScan.imageUrlScan(images);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion){
                case "review":
                    updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"图片中有不确定因素，需要人工审核");
                    flag=false;
                    break;
                case "block":
                    updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"图片中有违规内容，审核失败");
                    flag=false;
                    break;

            }
        } catch (Exception e) {
            e.printStackTrace();
            updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"阿里云调用失败，转为人工审核");
            flag=false;
        }

        return flag;
    }

    @Autowired
    GreenTextScan greenTextScan;

    /**
     * 调用阿里云安全接口  审核文本内容是否有违规信息
     * 如果阿里云返回的是 block 文章 status: 2 review 文章 status 3.出现异常 status 3
     * @param content
     * @param wmNews
     * @return
     */

    private boolean handleText(String content, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenTextScan.greenTextScan(content);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "review":
                    updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH.getCode(), "文本中有不确定因素，需要人工审核");
                    flag = false;
                    break;
                case "block":
                    updateWmNews(wmNews, WmNews.Status.FAIL.getCode(), "文本中有违规内容，审核失败");
                    flag = false;
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH.getCode(), "调用阿里云接口失败，转为人工审核");
            flag = false;
        }
        return flag;
    }

    @Autowired
    AdminFeign adminFeign;

    /**
     * 成功返回true 失败返回false 失败修改文章的状态
     * @param content
     * @param wmNews
     * @return
     */

    private boolean handleSensitive(String content, WmNews wmNews) {
        //1.查询敏感词列表
        ResponseResult<List<String>> selectAllChannelResult = adminFeign.selectAllChannel();
        if (selectAllChannelResult.getCode().intValue()!=0){
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR,"远程调用敏感词失败");
        }
        List<String> sensitives = selectAllChannelResult.getData();
        //2.DFA工具类 初始化DFA数据模型
        SensitiveWordUtil.initMap(sensitives);
        //3.使用DFA算法进行敏感词审核
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        //4.根据审核结果 修改wmNews
        if (map !=null && map.size()>0){
        updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"文本内容包含管理的敏感词：“map.toSting()");
        return false;
        }
        return true;
    }

    /**
     * 修改文章的状态
     * @param wmNews  文章
     * @param status 状态
     * @param msg 原因
     */

    public  void  updateWmNews(WmNews wmNews,Short status,String msg){
        wmNews.setReason(msg);
        wmNews.setStatus(status);
        wmNewsMapper.updateById(wmNews);

    }

    /**
     *
     * @param wmNews 文章对象
     * @return  Map<String,Object>  key: content 文本内容  value:string key：images 图片集合，List<String>    图片url集合
     */

    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        Map<String,Object> result = new HashMap<>();
        String contentJson = wmNews.getContent();
        List<Map> contentMaps = JSONArray.parseArray(contentJson, Map.class);
        //1.抽取内容
        String content = wmNews.getTitle();
        String collect = contentMaps.stream()
                .filter(map -> "text".equals(map.get("type")))
                .map(o -> (String) o.get("value"))
                .collect(Collectors.joining("-hmtt-"));
        //外面的花很美 _hmtt_国家很强大

        collect=collect+"-hmtt-"+content;
        result.put("content",collect);
        //2.抽取图片  content中包含所有的图片  封面中包含所有图片  放到同一个集合  最后去重
        List<String> images = contentMaps.stream()
                .filter(map -> "images".equals(map.get("type")))
                .map(o -> (String) o.get("value"))
                .collect(Collectors.toList());
        if (StringUtils.isNotBlank(wmNews.getImages())){
            List<String> coverImage  = Arrays.stream(wmNews.getImages().split(","))
                    .map(url -> webSite + url)
                    .collect(Collectors.toList());
            images.addAll(coverImage);
        }
        //去重
        images= images.stream().distinct().collect(Collectors.toList());
        result.put("images",images);
        return result;
    }
}
